package com.chouxiaozi.miniprogram.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    Logger logger = LoggerFactory.getLogger(RedisUtil.class);

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 批量删除对应的value
     *
     * @param keys
     */
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    /**
     * 批量删除key
     *
     * @param pattern
     */
    public void removePattern(final String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        if (redisTemplate.keys(pattern).size() > 0)
            redisTemplate.delete(keys);
    }

    /**
     * 删除对应的value
     *
     * @param key
     */
    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }

    /**
     * 判断缓存中是否有对应的value
     *
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public Object get(final String key) {
        Object result = null;
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 写入缓存(hset)
     *
     * @param key
     * @param value
     * @return
     */
    public boolean hset(final String key, final String hashKey, Object value, Long expireTime) {
        boolean result = false;
        try {
            HashOperations<String, String, Object> operations = redisTemplate
                    .opsForHash();
            operations.put(key, hashKey, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取过期时间(getExpire)
     *
     * @param key
     * @return
     */
    public Long getExpire(final String key) {
        Long time = 0L;
        try {
            time = redisTemplate.opsForValue().getOperations().getExpire(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return time;
    }

    /**
     * 写入缓存(hset)
     *
     * @param key
     * @param value
     * @return
     */
    public boolean hset(final String key, final String hashKey, Object value) {
        boolean result = false;
        try {
            redisTemplate.opsForHash().put(key, hashKey, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 读取缓存(hget)
     *
     * @param key
     * @return
     */
    public Object hget(final String key, final String hashKey) {
        Object result = null;
        result = redisTemplate.opsForHash().get(key, hashKey);
        return result;
    }

    /**
     * 读取缓存(hget)
     *
     * @param key
     * @return
     */
    public boolean hdel(final String key, final String hashKey) {
        boolean result = false;
        try {
            redisTemplate.opsForHash().delete(key, hashKey);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 返回哈希表 key 中所有的域名hashKey
     *
     * @param key
     * @return
     */
    public Set<String> hgetAllKeys(final String key) {
        Set<String> result = null;
        HashOperations<String, String, Object> operations = redisTemplate
                .opsForHash();
        result = operations.keys(key);
        return result;
    }

    /**
     * 返回哈希表 key 中所有域的值
     *
     * @param key
     * @return
     */
    public List<Object> hgetAllValues(final String key) {
        List<Object> result = null;
        result = redisTemplate.opsForHash().values(key);
        return result;
    }

    /**
     * 读取缓存(hgetAll)
     *
     * @param key
     * @return
     */
    public Map<Object, Object> hgetAll(final String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    public void lpush(final String key, final Object value) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        operations.leftPush(key, value);
    }

    public boolean leftPushAll(final String key, final List list, Long expireTime) {
        boolean result = false;
        try {
            ListOperations<String, Object> operations = redisTemplate.opsForList();
            operations.leftPushAll(key, list);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            logger.error("写入redis缓存发生错误", e);
        }
        return result;
    }

    public Object rpop(final String key) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        return operations.rightPop(key);
    }

    public Object index(final String key, final int index) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        return operations.index(key, index);
    }

    public List range(final String key, final int start, final int end) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        return operations.range(key, start, end);
    }

    public Long increment(final String key) {
        return redisTemplate.opsForValue().increment(key, 1);
    }

    public Long increment(final String key, final long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }


    public RedisTemplate getRedisTemplate() {
        return this.redisTemplate;
    }

    /**
     * 有序集合添加
     *
     * @param key
     * @param value
     * @param scoure
     */
    public void zsset(String key, String value, double scoure) {
        try {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            zset.add(key, value, scoure);
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
    }

    /**
     * 有序集合获取
     *
     * @param key
     * @param scoure
     * @param scoure1
     * @return
     */
    public Set<Object> zsget(String key, double scoure, double scoure1) {
        try {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.rangeByScore(key, scoure, scoure1);
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
    }

    /**
     * 删除zset元素
     *
     * @param key
     * @param val
     * @return
     */
    public boolean zdel(String key, String... val) {
        try {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.remove(key, val) > 0;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
        return false;
    }

    /**
     * 写入缓存设置时效时间
     *
     * @param key
     * @param value
     * @return
     */
    public boolean setExp(final String key, String value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<String, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
        return result;
    }

    /**
     * 获取范围的元素来自start于end从下令从低分到高分排序集。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<Object> rangeByScore(String key, long start, long end) {
        try {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.rangeByScore(key, start, end);
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
    }


    public Double getScore(String key, String member) {
        try {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.score(key, member);
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
    }

    public void setExpire(String key, long expireTime, TimeUnit unit) {
        try {
            redisTemplate.expire(key, expireTime, unit);
        } finally {
            RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
        }
    }
}
